﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Windows.Forms;
//using SharpMap.Geometries;
using GeoAPI.Geometries;

namespace SpectationClient.DataBaseDescription {
    [Serializable()]
    public class ColumnInfoFile : ColumnInfo {
        public enum RelatedColumnTypes : int {
            //General file descriptions
            cfile,
            cfile_hdr,
            cfiletype,
            cfileextension,
            cfilename,
            cdatatype,
            cdatetime,

            //Spectrum file related columns
            cspec_type,
            cspec_n_bands,
            cspec_fwhm,
            cspec_wl_min,
            cspec_wl_max,
            cspec_sample_count,

            //Image file related columns
            cimg_type,
            cimg_preview,
            cimg_rex_x,
            cimg_res_y,
            cimg_dpi,

            //General File options: 0xx
            /*
            std_unknown = 0,
            cfile = 1,  //the column_dgv with the main file
            cfile_hdr = 2,   //column_dgv with the header file
            cfilename = 3,  //column_dgv with the file name
            //cfiletype = 4,   //column_dgv with the file extentions 
            cfiletype = 5,  //Filetype (if possible to detect from BLOB)
            cdatatype = 6, //DataTyp
            std_DateTime = 7,
            */
            //Common Spectrum Attributes
            /*
            spec_type = 10,
            spec_wl_min = 11,
            spec_wl_max = 12,
            spec_n_bands = 13,
            spec_spectype = 14,
            spec_sample_count = 15,
            spec_fwhm = 16,
            */
            
            //ASD Spectra
            /*
            asd_co          = 101,	// Three character company name
            asd_comments    = 102,	// comment field
            asd_when        = 103,	// time when spectrum was saved
            asd_program_version = 104,	// ver. of the programcreatinf this file.
            // major ver in upper nibble, minY in lower
            asd_file_version    = 105,	// spectrum file format version
            asd_itime           = 106,	// Not used after v2.00
            asd_dc_corr         = 107,	// 1 if DC subtracted, 0 if not
            asd_dc_time         = 108,	// Time of last dc, seconds since 1/1/1970
            asd_data_type       = 109,	// see *_TYPE below
            asd_ref_time        = 110,	// Time of last wr, seconds since 1/1/1970
            asd_ch1_wavel       = 111,	// calibrated starting wavelength in nm
            asd_ch_last_wavel   = 112,  // last wavelength
            asd_wavel_step      = 113,	// calibrated wavelength step in nm
            asd_data_format     = 114,	// format of spectrum.
            asd_old_dc_count    = 115,	// Num of DC measurements in the avg
            asd_old_ref_count   = 116,	// Num of WR in the average
            asd_old_sample_count    = 117,	// Num of ba samples in the avg
            asd_application         = 118,	// Which application created APP_DATA
            asd_channels            = 119,	// Num of channels in the detector
            asd_app_data            = 120,	// Application-specific data
            asd_gps_data            = 121,	// GPS position, course, etc.
            asd_it                  = 122,	// The actual integration time in ms
            asd_fo                  = 123,	// The fo attachment's view in degrees
            asd_dcc                 = 124,	// The dark current correction value
            asd_calibration         = 125,	// calibration series
            asd_instrument_num      = 126,	// instrument number
            asd_ymin                = 127,	// setting of the y axis' minY value
            asd_ymax                = 128,	// setting of the y axis' maxY value
            asd_xmin                = 129,	// setting of the x axis' minY value
            asd_xmax                = 130,	// setting of the x axis' maxY value
            asd_ip_numbits          = 131,	// instrument's dynamic range
            asd_xmode               = 132,	// x axis mode. See *_XMODE
            asd_flags               = 133,	// Flags (0 = AVGFIX'ed)
            asd_dc_count            = 134,	// Num of DC measurements in the avg
            asd_ref_count           = 135,	// Num of WR in the average
            asd_sample_count        = 136,	// Num of ba samples in the avg
            asd_instrument          = 137,	// Instrument type. See defs below
            asd_bulb                = 138,	// The id number of the cal bulb
            asd_swir1_gain          = 139,	// gain setting for swir 1
            asd_swir2_gain          = 140,	// gain setting for swir 2 
            asd_swir1_offset        = 141,   	// offset setting for swir 1
            asd_swir2_offset        = 142,   	// offset setting for swir 2
            asd_splice1_wavelength  = 143,	// wavelength of VNIR and SWIR1 splice
            asd_splice2_wavelength  = 145,	// wavelength of SWIR1 and SWIR2 splice
            asd_when_in_ms          = 146,	// fill to 484 Bytes
            asd_spare               = 147,	// fill to 484 Bytes
            asd_spectrum_type       = 148,  // REF, ABS, ...

            asd_spectrum_name       = 149, 
             */

            //ENVI Data File  = 2xx
            /*
            envi_Description        = 201,
            envi_NSamples           = 202,
            envi_NLines             = 203,
            envi_Nbands             = 204,
            envi_HeaderOffset       = 205,
            envi_FileType           = 206,
            envi_Interleave         = 207,
            envi_DataType           = 208,
            envi_SensorType         = 209,
            envi_ByteOrder          = 210,
            envi_WavelengthUnits    = 211,
            envi_ReflectanceScaleFactor = 212,
            envi_Z_Plot_Range       = 213,
            envi_Z_Plot_min         = 214,
            envi_Z_Plot_max         = 215,
            envi_Z_Plot_Titles      = 216,
            envi_BandNames          = 217,
            envi_SpectraNames       = 218,
            envi_WaveLength         = 219,
            envi_spectrumname       = 220, //name of spectrum with the "spectrum name = {...}" part
            */
            
            //Images (without seperated header) = 3xx
            /*
            img_type = 301,  //column_dgv with the file type, e.g. "jpg", "mp3"
            img_preview = 302,
            img_res_x = 303,
            img_res_y = 304,
            img_res_dpi = 305
             */
        }
        protected Dictionary<String, RelatedColumnTypes> relatedColumns = new Dictionary<string, RelatedColumnTypes>();
        public ColumnInfo FilenameColumn { get; set; }
        
        #region Constructors
        public ColumnInfoFile(String columnName):base(columnName) {
            this.init(columnName, false);
        }
        public ColumnInfoFile(String columnName, bool isautogenerated):base(columnName) {
                this.init(columnName, isautogenerated);    
        }

        protected void init(string columnName, bool isAutogenerated) {
            base.init(columnName,  isAutogenerated, typeof(Byte[]));
        }

        #endregion 

        public override string ToString() {
            return String.Format("ColumnInfoFile:{0}", this.Name);
        }


        #region Handling of related columns

        virtual public void setRelatedColumn(String ColumnName, RelatedColumnTypes type) {
            if(this.Table == null) throw new Exception(String.Format("Column {0} is not connected to a TableInfo,", this.name));
            if(!this.Table.ContainsKey(ColumnName)) throw new Exception(String.Format("Column {0} does not exist in Table {1}", ColumnName, this.Table));
            this.relatedColumns.Add(ColumnName, type);

            switch(type) {
                case RelatedColumnTypes.cfilename: this.FilenameColumn = this.Table[ColumnName]; break;
                
            
            }

        }

        public Dictionary<String, RelatedColumnTypes> RelatedColumns {
            get { return this.relatedColumns; }
        }

        public void addFileValues(FileInfo fi, DataRow row) {
            Dictionary<String, Object> D = getValuesForColumns(fi);
            setValuesToRow(D, row);
        }

        public void addFileValues(FileInfo fi, DataGridViewRow row) {
            Dictionary<String, Object> D = getValuesForColumns(fi);
            setValuesToRow(D, row);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnValues">Dictonary with key=column name and value=the value to add</param>
        /// <param name="iPoint"></param>
        /// <param name="overwrite">if set on false, existing cell values will be not replaced</param>
        protected void setValuesToRow(Dictionary<String, Object> columnValues, DataGridViewRow row) {
            foreach (String column in columnValues.Keys) {
                if(row.DataGridView.Columns.Contains(column)){
                    row.Cells[column].Value = columnValues[column] !=null ? columnValues[column] : DBNull.Value;
                }
            }
        }

        protected void setValuesToRow(Dictionary<String, Object> columnValues, DataRow row) {
            foreach (String column in columnValues.Keys) {
                if(row.Table.Columns.Contains(column)) {
                    row[column] = columnValues[column];
                }
            }            
        }

        /// <summary>
        /// Removes all iPoint values that are related to this column
        /// </summary>
        /// <param name="iPoint">The iPoint whose values are to clean</param>
        public void cleanValues(DataRow row) {
            foreach (String column in this.relatedColumns.Keys) {
                if(row.Table.Columns.Contains(column)) {
                    row[column] = null;
                }
            }
        }

        /// <summary>
        /// Removes all iPoint values that are related to this column
        /// </summary>
        /// <param name="iPoint">The iPoint whose values are to clean</param>
        public void cleanValues(DataGridViewRow row) {
            foreach(String column in this.relatedColumns.Keys) {
                if(row.DataGridView.Columns.Contains(column)) {
                    row.Cells[column].Value = DBNull.Value;
                }
            }
        }

        /// <summary>
        /// Reads a file and returns its values for related columns:
        /// fileByteArrayit as Byte[], file name, file extension and file type 
        /// </summary>
        /// <param name="fileInfo">FileInfo pointing to a file.</param>
        /// <returns>
        ///     
        /// </returns>
        protected virtual Dictionary<String, Object> getValuesForColumns(FileInfo fileInfo) {
            Dictionary<String, Object> relatedValues = new Dictionary<string, object>();
            Byte[] fileByteArray = File.ReadAllBytes(fileInfo.FullName);

            foreach (String column in this.RelatedColumns.Keys) {
                
                //Treat all standard filecolumntype 
                RelatedColumnTypes relatedType = relatedColumns[column];
                switch (relatedType) {
                    case RelatedColumnTypes.cfile: relatedValues.Add(column, fileByteArray); break;
                    case RelatedColumnTypes.cfilename: relatedValues.Add(column, fileInfo.Name); break;
                    case RelatedColumnTypes.cfileextension : relatedValues.Add(column, fileInfo.Extension.Remove(0,1)); break;
                    case RelatedColumnTypes.cfiletype: relatedValues.Add(column, BLOBInfo.getFileExtension(fileByteArray)); break;
                }
            }
            return relatedValues;
        }

        #endregion

    }



}
